{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "java"
    }
   },
   "outputs": [],
   "source": [
    "%classpath add ../../../../../../target/classes\n",
    "import designpattern.adapter.tree.*;\n",
    "import java.util.stream.Collectors;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 适配器模式的结构\n",
    "![](images/adapter.png)\n",
    "\n",
    "在这个结构中，抽象出Target接口是适配器模式的关键。\n",
    "\n",
    "Target接口定义了客户端期望的接口，而Adaptee是已经被适配的接口。Adapter类将Adaptee接口适配成Target接口。\n",
    "\n",
    "一个显示树形结构的框架使用了适配器模式，这个框架中，对Target的抽象有两个接口：\n",
    "\n",
    "- TreeContentProvider：定义了树形结构的内容\n",
    "- NameProvider：定义了树形结构的名称\n",
    "\n",
    "\n",
    "![](images/treeviewer.png)\n",
    "\n",
    "\n",
    "在我们下面的演示中，为了表现这个设计的灵活性，假设有多种显示树的方式，比如：\n",
    "\n",
    "- 简单的文本显示\n",
    "  \n",
    "```plantext\n",
    "    1\n",
    "    2\n",
    "        4\n",
    "        5\n",
    "            7\n",
    "        6\n",
    "    3\n",
    "```    \n",
    "- 图形化显示\n",
    "\n",
    "```plantext\n",
    "    ├── 1\n",
    "    ├── 2\n",
    "    │   ├── 4\n",
    "    │   ├── 5\n",
    "    │   │   └── 7\n",
    "    │   └── 6\n",
    "    └── 3 \n",
    "```\n",
    "\n",
    "如果这两种TreeViewer分别是SimpleTreeViewer和VisualTreeViewer，那么同样一组TreeContentProvider和NameProvider，可以适配成不同的TreeViewer。\n",
    "\n",
    "TreeViewer和TreeContentProvider、NameProvider的设计和实现是这个模式的关键，实际上具有一定的工作量。代码在SimpleTree.java和VisualTreeView.java中。\n",
    "\n",
    "下面我们用这两个类来演示适配器模式的使用，同时也做一个简单的测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "vscode": {
     "languageId": "java"
    }
   },
   "outputs": [],
   "source": [
    "TreeContentProvider<Integer> contentProvider = new TreeContentProvider<Integer>() {\n",
    "    @Override\n",
    "    public List<Integer> getRoots() {\n",
    "        return Arrays.asList(1, 2, 3);\n",
    "    }\n",
    "\n",
    "    @Override\n",
    "    public List<Integer> getChildren(Integer parent) {\n",
    "        if (parent == 2) {\n",
    "            return Arrays.asList(4, 5, 6);\n",
    "        } else if (parent == 5) {\n",
    "            return Arrays.asList(7);\n",
    "        } else {\n",
    "            return List.of();\n",
    "        }\n",
    "    }\n",
    "};\n",
    "NameProvider<Integer> nameProvider = new NameProvider<Integer>() {\n",
    "    @Override\n",
    "    public String getName(Integer node) {\n",
    "        return node.toString();\n",
    "    }\n",
    "};\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "显示一个简单的树"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "vscode": {
     "languageId": "java"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "    4\n",
      "    5\n",
      "        7\n",
      "    6\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "new SimpleTreeViewer(contentProvider, nameProvider).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "显示一个可视化的树"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "vscode": {
     "languageId": "java"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "├── 1\n",
      "├── 2\n",
      "│   ├── 4\n",
      "│   ├── 5\n",
      "│   │   └── 7\n",
      "│   └── 6\n",
      "└── 3\n"
     ]
    }
   ],
   "source": [
    "new VisualTreeViewer(contentProvider,nameProvider).show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Java",
   "language": "java",
   "name": "java"
  },
  "language_info": {
   "codemirror_mode": "java",
   "file_extension": ".jshell",
   "mimetype": "text/x-java-source",
   "name": "Java",
   "pygments_lexer": "java",
   "version": "11.0.21+9-LTS"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
